package com.nanhai.buddhist.college.module.collegebase.service.departments;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.nanhai.buddhist.college.framework.common.exception.util.ServiceExceptionUtil;
import com.nanhai.buddhist.college.framework.common.pojo.PageResult;
import com.nanhai.buddhist.college.framework.common.util.collection.CollectionUtils;
import com.nanhai.buddhist.college.framework.common.util.number.NumberUtils;
import com.nanhai.buddhist.college.framework.datapermission.core.annotation.DataPermission;
import com.nanhai.buddhist.college.framework.security.core.util.SecurityFrameworkUtils;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.departments.vo.DepartmentsCreateReqVO;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.departments.vo.DepartmentsExportReqVO;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.departments.vo.DepartmentsPageReqVO;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.departments.vo.DepartmentsUpdateReqVO;
import com.nanhai.buddhist.college.module.collegebase.convert.departments.DepartmentsConvert;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.classes.ClassesDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.colleges.CollegesDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.departments.DepartmentsDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.professions.ProfessionsCountDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.professions.ProfessionsDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.studentroll.StudentRollDO;
import com.nanhai.buddhist.college.module.collegebase.dal.mysql.classes.ClassesMapper;
import com.nanhai.buddhist.college.module.collegebase.dal.mysql.colleges.CollegesMapper;
import com.nanhai.buddhist.college.module.collegebase.dal.mysql.departments.DepartmentsMapper;
import com.nanhai.buddhist.college.module.collegebase.dal.mysql.professions.ProfessionsMapper;
import com.nanhai.buddhist.college.module.collegebase.dal.mysql.studentroll.StudentRollMapper;
import com.nanhai.buddhist.college.module.collegebase.enums.ErrorCodeConstants;
import com.nanhai.buddhist.college.module.system.api.user.AdminUserApi;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 学校管理--系部 Service 实现类
 *
 * @author 开发
 */
@Service
@Validated
public class DepartmentsServiceImpl implements DepartmentsService {

    @Resource
    private DepartmentsMapper departmentsMapper;

    @Resource
    private ProfessionsMapper professionsMapper;

    @Resource
    private StudentRollMapper studentRollMapper;

    @Resource
    private CollegesMapper collegesMapper;

    @Resource
    private ClassesMapper classesMapper;


    @Resource
    private AdminUserApi adminUserApi;

    @Override
    public String createDepartments(DepartmentsCreateReqVO createReqVO) {
//        String userId = SecurityFrameworkUtils.getLoginUserId();
//        CommonResult<AdminUserRespDTO> users = adminUserApi.getUser(userId);
//        String permissionJson = users.getData().getPermissionJson();
//        UserPermissionListVo userPermissionListVo = JsonUtils.parseObject(permissionJson, UserPermissionListVo.class);
//
//        if(Objects.isNull(userPermissionListVo) || !userPermissionListVo.isDepartmentAll()){
//            throw ServiceExceptionUtil.exception(ErrorCodeConstants.DEPARTMENTS_NOT_ALLOW_CREATE);
//        }
        // 同学院下 校验系部昵称是否相同
        final Long count = departmentsMapper.selectCount(new LambdaQueryWrapper<DepartmentsDO>().eq(DepartmentsDO::getCollegeId, createReqVO.getCollegeId())
                .eq(DepartmentsDO::getDepartmentName, createReqVO.getDepartmentName()));

        if (ObjectUtil.isNotNull(count) && count > 0) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.DEPARTMENTS_NAME_HAVE_EXISTS);
        }

        // 获取代码
        String str = getCodeString(createReqVO);
        // 插入
        DepartmentsDO departments = DepartmentsConvert.INSTANCE.convert(createReqVO);


        departments.setCode(str);
        departments.setDepartmentNumber(NumberUtils.getCodeByServ("XB"));
        departmentsMapper.insert(departments);


        adminUserApi.saveUserCollegeData(SecurityFrameworkUtils.getLoginUserId(), 1, createReqVO.getCollegeId(), departments.getId());
        adminUserApi.initUserCollegeData(SecurityFrameworkUtils.getLoginUserId());


        // 返回
        return departments.getId();
    }

    @NotNull
    private String getCodeString(DepartmentsCreateReqVO createReqVO) {
        String str = "";
        // 获取父级代码
        CollegesDO collegesDO = collegesMapper.selectById(createReqVO.getCollegeId());

        // 获取流水号
        DepartmentsDO departmentsDO = departmentsMapper.selectOne(new LambdaQueryWrapper<DepartmentsDO>().orderByDesc(DepartmentsDO::getDepartmentCounter).last(" limit 1"));
        int departmentCounter = 0;
        if (Objects.isNull(departmentsDO)) {

        } else {
            departmentCounter = departmentsDO.getDepartmentCounter();
        }
        departmentCounter += 1;
        str = collegesDO.getCollegeCode() + departmentCounter;
        return str;
    }

    @Override
    public void updateDepartments(DepartmentsUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateDepartmentsExists(updateReqVO.getId());

        final Long count = departmentsMapper.selectCount(new LambdaQueryWrapper<DepartmentsDO>()
                .eq(DepartmentsDO::getCollegeId, updateReqVO.getCollegeId())
                .eq(DepartmentsDO::getDepartmentName, updateReqVO.getDepartmentName())
                .ne(DepartmentsDO::getId, updateReqVO.getId()));

        if (ObjectUtil.isNotNull(count) && count > 0) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.DEPARTMENTS_NAME_HAVE_EXISTS);
        }
        // 更新
        DepartmentsDO updateObj = DepartmentsConvert.INSTANCE.convert(updateReqVO);
        departmentsMapper.updateById(updateObj);

        adminUserApi.initUserCollegeData(SecurityFrameworkUtils.getLoginUserId());
    }

    @Override
    public void deleteDepartments(String id) {
        // 校验存在
        this.validateDepartmentsExists(id);

        if (ObjectUtil.isNotNull(adminUserApi.checkRoleUser(id).getData()) && adminUserApi.checkRoleUser(id).getData()) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.CHECK_USE_EXISTS);
        }
        // 删除
        departmentsMapper.deleteById(id);

        adminUserApi.initUserCollegeData(SecurityFrameworkUtils.getLoginUserId());
    }

    private void validateDepartmentsExists(String id) {
        if (departmentsMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.DEPARTMENTS_NOT_EXISTS);
        }
    }

    @Override
    @DataPermission(enable = false)
    public DepartmentsDO getDepartments(String id) {
        return departmentsMapper.selectById(id);
    }

    @Override
    @DataPermission(enable = false)
    public List<DepartmentsDO> getDepartmentsList(Collection<String> ids) {
        return CollectionUtils.isEmpty(ids) ? Collections.emptyList() : departmentsMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<DepartmentsDO> getDepartmentsPage(DepartmentsPageReqVO pageReqVO) {
        PageResult<DepartmentsDO> selectPage = departmentsMapper.selectPage(pageReqVO);
        Set<String> departmentIds = CollectionUtils.convertSet(selectPage.getList(), DepartmentsDO::getId);
        Map<String, ProfessionsCountDO> stringProfessionsCountDOMap = Collections.EMPTY_MAP;
        if (!departmentIds.isEmpty()) {
            List<ProfessionsCountDO> professionsCountDOS = professionsMapper.selectCountByDepartIds(departmentIds);
            stringProfessionsCountDOMap = CollectionUtils.convertMap(professionsCountDOS, ProfessionsCountDO::getDepartmentId);

        }

        if (CollectionUtil.isNotEmpty(selectPage.getList())) {
            for (DepartmentsDO departmentsDO : selectPage.getList()) {
                departmentsDO.setProfessionsCount(Optional.ofNullable(stringProfessionsCountDOMap).map(s -> s.get(departmentsDO.getId())).map(ProfessionsCountDO::getProfessionCount).orElse(0L));
                Long selectCount = studentRollMapper.selectCount(new LambdaUpdateWrapper<StudentRollDO>().eq(StudentRollDO::getDepartmentsId, departmentsDO.getId()));
                departmentsDO.setStudentCount(selectCount);
                //TODO 教师数量
            }
        }

        return selectPage;
    }

    @Override
    public List<DepartmentsDO> getDepartmentsList(DepartmentsExportReqVO exportReqVO) {
        return departmentsMapper.selectList(exportReqVO);
    }

    @Override
    public List<DepartmentsDO> getDepartmentsListByCollegeId(String collegeId) {
        return departmentsMapper.selectList(new QueryWrapper<DepartmentsDO>().lambda().eq(DepartmentsDO::getCollegeId, collegeId));
    }

    @Override
    public DepartmentsDO getDepartmentDTOByClassesId(String classesId) {
        ClassesDO classesDO = classesMapper.selectById(classesId);
        if (ObjectUtil.isNull(classesDO)) {
            return null;
        }
        ProfessionsDO professionsDO = professionsMapper.selectById(classesDO.getProfessionId());
        if (ObjectUtil.isNull(professionsDO)) {
            return null;
        }
        return departmentsMapper.selectById(professionsDO.getDepartmentsId());
    }

    @Override
    public List<DepartmentsDO> getDepartmentDTOByClassesIdList(Collection<String> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            return null;
        }
        List<ProfessionsDO> professionsDOS = professionsMapper.selectBatchIds(ids);
        if (CollectionUtil.isEmpty(professionsDOS)) {
            return null;
        }

        List<String> collect = professionsDOS.stream().map(ProfessionsDO::getDepartmentsId).distinct().collect(Collectors.toList());
        if (CollectionUtil.isEmpty(collect)) {
            return null;
        }
        return departmentsMapper.selectBatchIds(collect);
    }

}
